home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / usr / share / automake-1.9 / Automake / DisjConditions.pm < prev    next >
Encoding:
Perl POD Document  |  2005-10-13  |  14.1 KB  |  540 lines

  1. # Copyright (C) 1997, 2001, 2002, 2003, 2004  Free Software Foundation, Inc.
  2.  
  3. # This program is free software; you can redistribute it and/or modify
  4. # it under the terms of the GNU General Public License as published by
  5. # the Free Software Foundation; either version 2, or (at your option)
  6. # any later version.
  7.  
  8. # This program is distributed in the hope that it will be useful,
  9. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11. # GNU General Public License for more details.
  12.  
  13. # You should have received a copy of the GNU General Public License
  14. # along with this program; if not, write to the Free Software
  15. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  16. # 02110-1301, USA.
  17.  
  18. package Automake::DisjConditions;
  19.  
  20. use Carp;
  21. use strict;
  22. use Automake::Condition qw/TRUE FALSE/;
  23.  
  24. =head1 NAME
  25.  
  26. Automake::DisjConditions - record a disjunction of Conditions
  27.  
  28. =head1 SYNOPSIS
  29.  
  30.   use Automake::Condition;
  31.   use Automake::DisjConditions;
  32.  
  33.   # Create a Condition to represent "COND1 and not COND2".
  34.   my $cond = new Automake::Condition "COND1_TRUE", "COND2_FALSE";
  35.   # Create a Condition to represent "not COND3".
  36.   my $other = new Automake::Condition "COND3_FALSE";
  37.  
  38.   # Create a DisjConditions to represent
  39.   #   "(COND1 and not COND2) or (not COND3)"
  40.   my $set = new Automake::DisjConditions $cond, $other;
  41.  
  42.   # Return the list of Conditions involved in $set.
  43.   my @conds = $set->conds;
  44.  
  45.   # Return one of the Condition involved in $set.
  46.   my $cond = $set->one_cond;
  47.  
  48.   # Return true iff $set is always true (i.e. its subconditions
  49.   # conver all cases).
  50.   if ($set->true) { ... }
  51.  
  52.   # Return false iff $set is always false (i.e. is empty, or contains
  53.   # only false conditions).
  54.   if ($set->false) { ... }
  55.  
  56.   # Return a string representing the DisjConditions.
  57.   #   "COND1_TRUE COND2_FALSE | COND3_FALSE"
  58.   my $str = $set->string;
  59.  
  60.   # Return a human readable string representing the DisjConditions.
  61.   #   "(COND1 and !COND2) or (!COND3)"
  62.   my $str = $set->human;
  63.  
  64.   # Merge (OR) several DisjConditions.
  65.   my $all = $set->merge($set2, $set3, ...)
  66.  
  67.   # Invert a DisjConditions, i.e., create a new DisjConditions
  68.   # that complements $set.
  69.   my $inv = $set->invert;
  70.  
  71.   # Multiply two DisjConditions.
  72.   my $prod = $set1->multiply ($set2);
  73.  
  74.   # Return the subconditions of a DisjConditions with respect to
  75.   # a Condition.  See the description for a real example.
  76.   my $subconds = $set->sub_conditions ($cond);
  77.  
  78.   # Check whether a new definition in condition $cond would be
  79.   # ambiguous w.r.t. existing definitions in $set.
  80.   ($msg, $ambig_cond) = $set->ambiguous_p ($what, $cond);
  81.  
  82. =head1 DESCRIPTION
  83.  
  84. A C<DisjConditions> is a disjunction of C<Condition>s.  In Automake
  85. they are used to represent the conditions into which Makefile
  86. variables and Makefile rules are defined.
  87.  
  88. If the variable C<VAR> is defined as
  89.  
  90.   if COND1
  91.     if COND2
  92.       VAR = value1
  93.     endif
  94.   endif
  95.   if !COND3
  96.     if COND4
  97.       VAR = value2
  98.     endif
  99.   endif
  100.  
  101. then it will be associated a C<DisjConditions> created with
  102. the following statement.
  103.  
  104.   new Automake::DisjConditions
  105.     (new Automake::Condition ("COND1_TRUE", "COND2_TRUE"),
  106.      new Automake::Condition ("COND3_FALSE", "COND4_TRUE"));
  107.  
  108. As you can see, a C<DisjConditions> is made from a list of
  109. C<Condition>s.  Since C<DisjConditions> is a disjunction, and
  110. C<Condition> is a conjunction, the above can be read as
  111. follows.
  112.  
  113.   (COND1 and COND2) or ((not COND3) and COND4)
  114.  
  115. That's indeed the condition into which C<VAR> has a value.
  116.  
  117. Like C<Condition> objects, a C<DisjConditions> object is unique
  118. with respect to its conditions.  Two C<DisjConditions> objects created
  119. for the same set of conditions will have the same adress.  This makes
  120. it easy to compare C<DisjConditions>s: just compare the references.
  121.  
  122. =head2 Methods
  123.  
  124. =over 4
  125.  
  126. =item C<$set = new Automake::DisjConditions [@conds]>
  127.  
  128. Create a C<DisjConditions> object from the list of C<Condition>
  129. objects passed in arguments.
  130.  
  131. If the C<@conds> list is empty, the C<DisjConditions> is assumed to be
  132. false.
  133.  
  134. As explained previously, the reference (object) returned is unique
  135. with respect to C<@conds>.  For this purpose, duplicate elements are
  136. ignored.
  137.  
  138. =cut
  139.  
  140. # Keys in this hash are DisjConditions strings. Values are the
  141. # associated object DisjConditions.  This is used by `new' to reuse
  142. # DisjConditions objects with identical conditions.
  143. use vars '%_disjcondition_singletons';
  144.  
  145. sub new ($;@)
  146. {
  147.   my ($class, @conds) = @_;
  148.   my $self = {
  149.     hash => {},
  150.   };
  151.   bless $self, $class;
  152.  
  153.   for my $cond (@conds)
  154.     {
  155.       confess "`$cond' isn't a reference" unless ref $cond;
  156.       confess "`$cond' isn't an Automake::Condition"
  157.     unless $cond->isa ("Automake::Condition");
  158.  
  159.       # This is a disjunction of conditions, so we drop
  160.       # false conditions.  We'll always treat an "empty"
  161.       # DisjConditions as false for this reason.
  162.       next if $cond->false;
  163.  
  164.       # Store conditions as keys AND as values, because blessed
  165.       # objects are converted to string when used as keys (so
  166.       # at least we still have the value when we need to call
  167.       # a method).
  168.       $self->{'hash'}{$cond} = $cond;
  169.     }
  170.  
  171.   my $key = $self->string;
  172.   if (exists $_disjcondition_singletons{$key})
  173.     {
  174.       return $_disjcondition_singletons{$key};
  175.     }
  176.   $_disjcondition_singletons{$key} = $self;
  177.   return $self;
  178. }
  179.  
  180. =item C<@conds = $set-E<gt>conds>
  181.  
  182. Return the list of C<Condition> objects involved in C<$set>.
  183.  
  184. =cut
  185.  
  186. sub conds ($ )
  187. {
  188.   my ($self) = @_;
  189.   return @{$self->{'conds'}} if exists $self->{'conds'};
  190.   my @conds = values %{$self->{'hash'}};
  191.   @conds = sort { $a->string cmp $b->string } @conds;
  192.   $self->{'conds'} = [@conds];
  193.   return @conds;
  194. }
  195.  
  196. =item C<$cond = $set-E<gt>one_cond>
  197.  
  198. Return one C<Condition> object involved in C<$set>.
  199.  
  200. =cut
  201.  
  202. sub one_cond ($)
  203. {
  204.   my ($self) = @_;
  205.   return (%{$self->{'hash'}},)[1];
  206. }
  207.  
  208. =item C<$et = $set-E<gt>false>
  209.  
  210. Return 1 iff the C<DisjConditions> object is always false (i.e., if it
  211. is empty, or if it contains only false C<Condition>s). Return 0
  212. otherwise.
  213.  
  214. =cut
  215.  
  216. sub false ($ )
  217. {
  218.   my ($self) = @_;
  219.   return 0 == keys %{$self->{'hash'}};
  220. }
  221.  
  222. =item C<$et = $set-E<gt>true>
  223.  
  224. Return 1 iff the C<DisjConditions> object is always true (i.e. covers all
  225. conditions). Return 0 otherwise.
  226.  
  227. =cut
  228.  
  229. sub true ($ )
  230. {
  231.   my ($self) = @_;
  232.   return $self->invert->false;
  233. }
  234.  
  235. =item C<$str = $set-E<gt>string>
  236.  
  237. Build a string which denotes the C<DisjConditions>.
  238.  
  239. =cut
  240.  
  241. sub string ($ )
  242. {
  243.   my ($self) = @_;
  244.  
  245.   return $self->{'string'} if defined $self->{'string'};
  246.  
  247.   my $res = '';
  248.   if ($self->false)
  249.     {
  250.       $res = 'FALSE';
  251.     }
  252.   else
  253.     {
  254.       $res = join (' | ', map { $_->string } $self->conds);
  255.     }
  256.  
  257.   $self->{'string'} = $res;
  258.   return $res;
  259. }
  260.  
  261. =item C<$cond-E<gt>human>
  262.  
  263. Build a human readable string which denotes the C<DisjConditions>.
  264.  
  265. =cut
  266.  
  267. sub human ($ )
  268. {
  269.   my ($self) = @_;
  270.  
  271.   return $self->{'human'} if defined $self->{'human'};
  272.  
  273.   my $res = '';
  274.   if ($self->false)
  275.     {
  276.       $res = 'FALSE';
  277.     }
  278.   else
  279.     {
  280.       my @c = $self->conds;
  281.       if (1 == @c)
  282.     {
  283.       $res = $c[0]->human;
  284.     }
  285.       else
  286.     {
  287.       $res = '(' . join (') or (', map { $_->human } $self->conds) . ')';
  288.     }
  289.     }
  290.   $self->{'human'} = $res;
  291.   return $res;
  292. }
  293.  
  294.  
  295. =item C<$newcond = $cond-E<gt>merge (@otherconds)>
  296.  
  297. Return a new C<DisjConditions> which is the disjunction of
  298. C<$cond> and C<@otherconds>.  Items in C<@otherconds> can be
  299. @C<Condition>s or C<DisjConditions>.
  300.  
  301. =cut
  302.  
  303. sub merge ($@)
  304. {
  305.   my ($self, @otherconds) = @_;
  306.   new Automake::DisjConditions (
  307.     map { $_->isa ("Automake::DisjConditions") ? $_->conds : $_ }
  308.         ($self, @otherconds));
  309. }
  310.  
  311.  
  312. =item C<$prod = $set1-E<gt>multiply ($set2)>
  313.  
  314. Multiply two conditional sets.
  315.  
  316.   my $set1 = new Automake::DisjConditions
  317.     (new Automake::Condition ("A_TRUE"),
  318.      new Automake::Condition ("B_TRUE"));
  319.   my $set2 = new Automake::DisjConditions
  320.     (new Automake::Condition ("C_FALSE"),
  321.      new Automake::Condition ("D_FALSE"));
  322.  
  323. C<$set1-E<gt>multiply ($set2)> will return
  324.  
  325.   new Automake::DisjConditions
  326.     (new Automake::Condition ("A_TRUE", "C_FALSE"),
  327.      new Automake::Condition ("B_TRUE", "C_FALSE"),;
  328.      new Automake::Condition ("A_TRUE", "D_FALSE"),
  329.      new Automake::Condition ("B_TRUE", "D_FALSE"));
  330.  
  331. The argument can also be a C<Condition>.
  332.  
  333. =cut
  334.  
  335. # Same as multiply() but take a list of Conditonals as second argument.
  336. # We use this in invert().
  337. sub _multiply ($@)
  338. {
  339.   my ($self, @set) = @_;
  340.   my @res = map { $_->multiply (@set) } $self->conds;
  341.   return new Automake::DisjConditions (Automake::Condition::reduce_or @res);
  342. }
  343.  
  344. sub multiply ($$)
  345. {
  346.   my ($self, $set) = @_;
  347.   return $self->_multiply ($set) if $set->isa('Automake::Condition');
  348.   return $self->_multiply ($set->conds);
  349. }
  350.  
  351. =item C<$inv = $set-E<gt>invert>
  352.  
  353. Invert a C<DisjConditions>.  Return a C<DisjConditions> which is true
  354. when C<$set> is false, and vice-versa.
  355.  
  356.   my $set = new Automake::DisjConditions
  357.     (new Automake::Condition ("A_TRUE", "B_TRUE"),
  358.      new Automake::Condition ("A_FALSE", "B_FALSE"));
  359.  
  360. Calling C<$set-E<gt>invert> will return the following C<DisjConditions>.
  361.  
  362.   new Automake::DisjConditions
  363.     (new Automake::Condition ("A_TRUE", "B_FALSE"),
  364.      new Automake::Condition ("A_FALSE", "B_TRUE"));
  365.  
  366. We implement the inversion by a product-of-sums to sum-of-products
  367. conversion using repeated multiplications.  Because of the way we
  368. implement multiplication, the result of inversion is in canonical
  369. prime implicant form.
  370.  
  371. =cut
  372.  
  373. sub invert($ )
  374. {
  375.   my ($self) = @_;
  376.  
  377.   return $self->{'invert'} if defined $self->{'invert'};
  378.  
  379.   # The invert of an empty DisjConditions is TRUE.
  380.   my $res = new Automake::DisjConditions TRUE;
  381.  
  382.   #   !((a.b)+(c.d)+(e.f))
  383.   # = (!a+!b).(!c+!d).(!e+!f)
  384.   # We develop this into a sum of product iteratively, starting from TRUE:
  385.   # 1) TRUE
  386.   # 2) TRUE.!a + TRUE.!b
  387.   # 3) TRUE.!a.!c + TRUE.!b.!c + TRUE.!a.!d + TRUE.!b.!d
  388.   # 4) TRUE.!a.!c.!e + TRUE.!b.!c.!e + TRUE.!a.!d.!e + TRUE.!b.!d.!e
  389.   #    + TRUE.!a.!c.!f + TRUE.!b.!c.!f + TRUE.!a.!d.!f + TRUE.!b.!d.!f
  390.   foreach my $cond ($self->conds)
  391.     {
  392.       $res = $res->_multiply ($cond->not);
  393.     }
  394.  
  395.   # Cache result.
  396.   $self->{'invert'} = $res;
  397.   # It's tempting to also set $res->{'invert'} to $self, but that
  398.   # is a bad idea as $self hasn't been normalized in any way.
  399.   # (Different inputs can produce the same inverted set.)
  400.   return $res;
  401. }
  402.  
  403. =item C<$self-E<gt>simplify>
  404.  
  405. Return a C<Disjunction> which is a simplified canonical form of C<$self>.
  406. This canonical form contains only prime implicants, but it can contain
  407. non-essential prime implicants.
  408.  
  409. =cut
  410.  
  411. sub simplify ($)
  412. {
  413.   my ($self) = @_;
  414.   return $self->invert->invert;
  415. }
  416.  
  417. =item C<$self-E<gt>sub_conditions ($cond)>
  418.  
  419. Return the subconditions of C<$self> that contains C<$cond>, with
  420. C<$cond> stripped.  More formally, return C<$res> such that
  421. C<$res-E<gt>multiply ($cond) == $self-E<gt>multiply ($cond)> and
  422. C<$res> does not mention any of the variables in C<$cond>.
  423.  
  424. For instance, consider:
  425.  
  426.   my $a = new Automake::DisjConditions
  427.     (new Automake::Condition ("A_TRUE", "B_TRUE"),
  428.      new Automake::Condition ("A_TRUE", "C_FALSE"),
  429.      new Automake::Condition ("A_TRUE", "B_FALSE", "C_TRUE"),
  430.      new Automake::Condition ("A_FALSE"));
  431.   my $b = new Automake::DisjConditions
  432.     (new Automake::Condition ("A_TRUE", "B_FALSE"));
  433.  
  434. Calling C<$a-E<gt>sub_conditions ($b)> will return the following
  435. C<DisjConditions>.
  436.  
  437.   new Automake::DisjConditions
  438.     (new Automake::Condition ("C_FALSE"), # From A_TRUE C_FALSE
  439.      new Automake::Condition ("C_TRUE")); # From A_TRUE B_FALSE C_TRUE"
  440.  
  441. =cut
  442.  
  443. sub sub_conditions ($$)
  444. {
  445.   my ($self, $subcond) = @_;
  446.  
  447.   # Make $subcond blindingly apparent in the DisjConditions.
  448.   # For instance `$b->multiply($a->conds)' (from the POD example) is:
  449.   #     (new Automake::Condition ("FALSE"),
  450.   #      new Automake::Condition ("A_TRUE", "B_FALSE", "C_FALSE"),
  451.   #      new Automake::Condition ("A_TRUE", "B_FALSE", "C_TRUE"),
  452.   #      new Automake::Condition ("FALSE"))
  453.   my @prodconds = $subcond->multiply ($self->conds);
  454.  
  455.   # Now, strip $subcond from the remaining (i.e., non-false) Conditions.
  456.   my @res = map { $_->false ? () : $_->strip ($subcond) } @prodconds;
  457.  
  458.   return new Automake::DisjConditions @res;
  459. }
  460.  
  461. =item C<($string, $ambig_cond) = $condset-E<gt>ambiguous_p ($what, $cond)>
  462.  
  463. Check for an ambiguous condition.  Return an error message and the
  464. other condition involved if we have an ambiguity.  Return an empty
  465. string and FALSE otherwise.
  466.  
  467. C<$what> is the name of the thing being defined, to use in the error
  468. message.  C<$cond> is the C<Condition> under which it is being
  469. defined.  C<$condset> is the C<DisjConditions> under which it had
  470. already been defined.
  471.  
  472. =cut
  473.  
  474. sub ambiguous_p ($$$)
  475. {
  476.   my ($self, $var, $cond) = @_;
  477.  
  478.   # Note that these rules don't consider the following
  479.   # example as ambiguous.
  480.   #
  481.   #   if COND1
  482.   #     FOO = foo
  483.   #   endif
  484.   #   if COND2
  485.   #     FOO = bar
  486.   #   endif
  487.   #
  488.   # It's up to the user to not define COND1 and COND2
  489.   # simultaneously.
  490.  
  491.   return ("$var multiply defined in condition " . $cond->human, $cond)
  492.     if exists $self->{'hash'}{$cond};
  493.  
  494.   foreach my $vcond ($self->conds)
  495.     {
  496.       return ("$var was already defined in condition " . $vcond->human
  497.           . ", which includes condition ". $cond->human, $vcond)
  498.     if $vcond->true_when ($cond);
  499.  
  500.       return ("$var was already defined in condition " . $vcond->human
  501.           . ", which is included in condition " . $cond->human, $vcond)
  502.     if $cond->true_when ($vcond);
  503.     }
  504.   return ('', FALSE);
  505. }
  506.  
  507. =head1 SEE ALSO
  508.  
  509. L<Automake::Condition>.
  510.  
  511. =head1 HISTORY
  512.  
  513. C<AM_CONDITIONAL>s and supporting code were added to Automake 1.1o by
  514. Ian Lance Taylor <ian@cygnus.org> in 1997.  Since then it has been
  515. improved by Tom Tromey <tromey@redhat.com>, Richard Boulton
  516. <richard@tartarus.org>, Raja R Harinath <harinath@cs.umn.edu>, Akim
  517. Demaille <akim@epita.fr>, Pavel Roskin <proski@gnu.org>, and
  518. Alexandre Duret-Lutz <adl@gnu.org>.
  519.  
  520. =cut
  521.  
  522. 1;
  523.  
  524. ### Setup "GNU" style for perl-mode and cperl-mode.
  525. ## Local Variables:
  526. ## perl-indent-level: 2
  527. ## perl-continued-statement-offset: 2
  528. ## perl-continued-brace-offset: 0
  529. ## perl-brace-offset: 0
  530. ## perl-brace-imaginary-offset: 0
  531. ## perl-label-offset: -2
  532. ## cperl-indent-level: 2
  533. ## cperl-brace-offset: 0
  534. ## cperl-continued-brace-offset: 0
  535. ## cperl-label-offset: -2
  536. ## cperl-extra-newline-before-brace: t
  537. ## cperl-merge-trailing-else: nil
  538. ## cperl-continued-statement-offset: 2
  539. ## End:
  540.